import {
  busFactory
} from './_Router.js';
import {
  clone,
  isEmptyObject
} from './util.js';
// import { Router } from './Router.js';



// 根据菜单生成的解析单元，_path包含路径解析信息
var routerBus;
//onChange , onBeforeChange 配置对象
var _config,
  _page, //当前显示的页面
  _oldPage, //上一个显示的页面
  _defaultPath;//没找到页面时默认跳转的路径 ，默认取app下第一个子页面

/**
 * Routerinfo 构造器 页面需要的一些信息
 * @param {Vue} _vue 当前实例
 */
function Info(_vue) {
  this.menus = [];
  this.pages = [];
  this.current = {};
  // this._Vue=_Vue;
  // console.log(_vue);
  //第一个实例化的会变成入口
  var _this = this;

  _vue.$nextTick(() => {
    getOnBus(_vue, _this)
    routerGo()
  })
}
/**
 * 移除页面
 * @param {Object} item 移除的页面
 */
Info.prototype.removePage = function (item) {
  var index = this.pages.indexOf(item);
  this.pages.splice(index, 1);

  var router = getRouterByPagename(item.pagename);


  if (this.current.pagename === item.pagename) {
    var last = this.pages[index - 1] || this.pages[index + 1];
    if (last) {
      var nrouter = getRouterByPagename(last.pagename);

      var hash = `#${nrouter.curpath}`;
      history.replaceState(null, '', hash);

      router.clearHash();
      hashChange(location.href);
    } else {
      //获取父级
      var phash = router.curpath.split('/' + item.pagename)[0] || _defaultPath;
      // if(!phash){
      //   throw new Error('路由跳转失败，找不到下一个路由，pages被清空。')
      // }else{
      phash = '#' + phash
      history.replaceState(null, '', phash);

      router.parentPagename ? getRouterByPagename(router.parentPagename).clearHash() : router.clearHash();
      this.current = {};
      Vue.nextTick(() => {
        hashChange(location.href);
      })
      //路由到父级
      // }
    }
  } else {
    router.clearHash();
  }
}

/**
 * 关联到路由总线上
 * @param {Vue} _vue 实例
 */
var getOnBus = function (_vue, routerinfo) {

  var router
  if (!routerBus._living) {
    // 转成入口
    router = routerBus
  } else {
    // 查找页面对应的router
    var pagename = _vue.$options._componentTag;
    router = getRouterByPagename(pagename);
  }
  router._living = _vue;
  router._info = routerinfo;

  if (router.children) {
    //初始化菜单
    var menus = []
    router.children.forEach((item) => {
      menus.push({
        pagename: item.pagename,
        name: item.name,
        path: item._path.path
      })
    })
    routerinfo.menus = menus;
  }

}
/**
 * 开车上路 嘀嘀嘀
 * @param {_Router}  router 激活的router
 */
var routerGo = function (router) {
  router || (router = routerBus);

  var _vue = router._living;
  if (!_vue) {
    //路由没初始化
    return;
  }

  //找到激活页
  var active = router.active;
  if (!active) {
    return;
  }

  var info = router._info,
    pagename = active.pagename;

  //解析参数
  var result = active._path.matchRegExp.exec(active.curpath);
  var keys = active._path.keys;
  var params,
    path;
  if (keys && keys.length) {
    params = {}
    keys.forEach((item, index) => {
      params[item.name] = result[index + 1]
    });
  }
  if (params) {
    path = active._path.toPath(params)
  }
  //是否以及加载过
  var page = info.pages.find(item => item.pagename === pagename);
  if (!page) {
    if(typeof active.component==="function"){
      active.component().then(res => {
        _vue.$options.components[pagename] = res.default;
        info.pages.push({
          pagename,
          name: active.name,
          path: path || active._path.path
        });
      });
    }else{
      _vue.$options.components[pagename] =  active.component;
      info.pages.push({
        pagename,
        name: active.name,
        path: path || active._path.path
      });
    }
    //转到created
    return;
  }

  if (pagename !== info.current.pagename) {
    //触发隐藏页面的hide事件
    if (info.current.pagename) {
      triggerHide(getRouterByPagename(info.current.pagename));
    }
    //设置当前页
    info.current = active.getPageInfo();
  }

  if (path) {
    page.path = info.current.path = path;
  }
    //处理历史记录上的参数
    var state =window.history.state;
    if(state&&state._rxpagename){
      var nstate=clone(state);
      if(nstate._rxpagename===page.pagename){
        delete  nstate._rxpagename;
        if(!isEmptyObject(nstate)){
          params=nstate;
        }
      }
    }
    active._living && active._living.onRouterShow && active._living.onRouterShow(params)

  //继续往走
  routerGo(active);
}
/**
 * 触发onHide事件
 * @param {String} pagename
 */
var triggerHide = function (router) {
  if (!router._living) {
    return;
  }
  router._living.onRouterHide && router._living.onRouterHide();
  router.allchildren.forEach(item => triggerHide(item))
}


var hashChange = function (newURL,fromGoto) {
  var hash = new URL(newURL).hash.slice(1);
  //获取初步的页面信息
  var page = getPageByHash(hash);

  //没找到页面
  if (!page) {
    //第一次
    if (!_page) {
      //没有解析到菜单会到首页去
      location.hash = _defaultPath//重新走hashChange
      return;
    };
    throw new Error(`没有找到对应的页面：${newURL}`);
  }

  //点击的页面正在显示子路由，更新一下地址栏，重新拿页面信息
  if (page.curpath && page.curpath !== hash) {
    // page.curpath.indexOf(hash) !== -1
    var dist = getDistRouter(hash);
    if( dist.curpath&&dist.curpath.indexOf(hash) !== -1){
      hash = dist.curpath;
      page = getPageByHash(hash);
      history.replaceState(history.state, '', '#' + hash);
      //不是goTo来的，正在显示中。
      dist = getDistRouter(hash);
      if(!fromGoto&&checkIsShowing(dist.pagename)){
        return;
      }
    }
  }
  // console.log(page)

  //检查页面
  checkPage(page,fromGoto).then(() => {
    //缓存老页面，老页面携带参数给新页面
    _oldPage = _page;
    _page = page;
    //更新bus中，本次的站点
    routerBus.setActive(hash)
    routerGo();
  }).catch(()=>{
     //第一次
     if (!_page) {
      //没有解析到菜单会到首页去
      location.hash = _defaultPath//重新走hashChange
    }else{
      history.back();
    }
  })
};

var getDistRouter = function (hash,parent=routerBus){
  var router = parent.allchildren.find(item => {
    return item._path.matchRegExp.exec(hash)
  });
  var crouter;
  if(router){
    crouter= getDistRouter(hash,router);
  }
  return crouter||router;
};

var checkPage = function (pageinfo,fromGoto) {
  var resolve,
    reject,
    promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    })
  if (fromGoto) {
    // goTo会进行预检查
    resolve();
  } else {
    var pagenames = []
    var getActivePagename = function (page) {
      if (page.active) {
        pagenames.push(page.active.pagename)
        getActivePagename(page.active)
      }
    }
    getActivePagename(pageinfo);
    var flag = _config.onBeforeChange ? _config.onBeforeChange(pagenames) : true;
    if (flag && flag.then) {
      //如果是promise
      return flag;
    } else {
      !typeof flag === 'boolean' || flag ? resolve() : reject()
    }
  }
  return promise
}

/**
 * 获取页面信息
 * @param {String} hash hash值
 */
var getPageByHash = function (hash) {

  var router = routerBus.allchildren.find(item => {
    return item._path.matchRegExp.exec(hash)
  });
  if (!router) {
    return;
  }
  return routerBus.getPageInfo(hash);
}

function checkIsShowing(pagename,active){
  active||(active=_page)
  if(active.pagename===pagename){
    return true;
  }
  if(!active.active){
    return false;
  }
  return checkIsShowing(pagename,active.active);
}

var goTo = function (pagename, params={}) {
  //找到页面
  var router = getRouterByPagename(pagename)
  if (!router) {
    throw new Error('没找到要goTo的页面。')
  }
  var hash = router._path.toPath(params);
  //编译参数 未编译的参数
  checkPage(getPageByHash(hash)).then(() => {
    hash='#'+hash;
    //转到新的路由
    params._rxpagename=pagename;
    //看是不是贴脸goTo
    var inFace=checkIsShowing(pagename);
    if(inFace){
      console.log('inFace');
      window.history.replaceState(params,'',hash)
    }else{
      window.history.pushState(params,'',hash)
    }
    hashChange(location.href,true);
  }).catch(()=>{
    //goTo 预检查
  })

}

/**
 * 根据页面名字获取路由
 * @param {String} pagename 页面名字
 * @param {_Routers} routers 路由组，不填默认routerBus的子路由
 */
var getRouterByPagename = function (pagename, routers = routerBus.allchildren) {
  if(routerBus.pagename===pagename){
    return routerBus;
  }
  for (var i = 0, j = routers.length; i < j; i++) {
    var item = routers[i];
    if (item.pagename == pagename) {
      return item;
    }
    var router;
    if (item.allchildren) {
      if (router = getRouterByPagename(pagename, item.allchildren)) {
        return router
      }
    }
  }
}

/**
 * 来，带上你的菜单和配置上车车
 * @param {Arrary} menus 菜单对象数组
 * @param {Object} config 配置项 onChange , onBeforeChange 必须有onChange 接收路由的变化
 */
var init = function (menus, config) {

  // 通过菜单解析Router 信息
  routerBus = busFactory(menus);

  //默认path
  _defaultPath=routerBus.children[0]._path.path;
  // 混入初始化
  Vue.mixin({
    created(){
      var pagename = this.$options._componentTag;
      if(pagename&&getRouterByPagename(pagename)){
        Vue.util.defineReactive(this,'$rxRouterInfo',new Info(this));
      }
    }
  })
  //直接赋值配置信息
  _config = config||{};

  // 加入退出路由的逻辑
  if(_config.onBeforeExit){
    //添加一条后退的历史记录
    var state=window.history.state;
    if(state&&typeof state.rxBack==='boolean'){
      state=state.oldState;
    }
    window.history.replaceState({
      rxBack:true,
      oldState:state
    },'',location.href);
    //
    window.history.pushState(state,'',location.href)
  }

  //解析当前href
  hashChange(location.href);

   //监听history变化
   var _isExiting=false;
  window.addEventListener('hashchange',function(ev) {
    //前进了
    if(_isExiting){
      _isExiting=false;
      //TODO 显示退出的提示
      _config.onCancelBeforeExit()
    }
    //当前的状态
    if(history.state&&history.state.rxBack){
      _isExiting=true;
      _config.onBeforeExit().then(()=>{
        _isExiting=false;
        window.history.back();
        window.location.reload();
      }).catch(()=>{
        _isExiting=false;
        window.history.forward();
      });
      return;
    }
    hashChange(location.href);

  });
}

var ex ={
  init,
  Info,
  goTo
}
Vue.prototype.$rxRouter = ex ;
